﻿using System;
using System.IO;
using System.Collections.Generic;
using DatabaseStuff;

namespace DatabaseStuff.Basic
{
    public abstract class TextDestination: IDBDestination
    {
        private TextStorageFormatSettings settings;

        public TextDestination()
        {
            settings = TextStorageFormatSettings.Default;
        }

        internal TextDestination(TextStorageFormatSettings _settings)
        {
            settings = _settings;
        }

        protected abstract TextWriter GetTableNamesWriter(IDatabase db);
        protected abstract TextWriter GetRecordsWriter(IDBTable table);
        protected abstract TextWriter GetSchemaWriter(IDBTable table);

        public void WriteData(IDatabase db)
        {
            IEnumerable<IDBTable> tables = db.GetTables();
            TextWriter writer;

            writer = GetTableNamesWriter(db);
            try
            { ExportTableNames(writer, tables); }
            finally
            { writer.Close(); }

            foreach (IDBTable t in tables)
            {
                writer = GetSchemaWriter(t);
                try
                { ExportSchema(writer, t.Schema); }
                finally
                { writer.Close(); }

                writer = GetRecordsWriter(t);
                try
                { ExportRecords(writer, t); }
                finally
                { writer.Close(); }
            }
        }

        private void ExportRecords(TextWriter writer, IDBTable table)
        {
            if (writer == null)
                throw new ArgumentNullException("writer");
            else if (table == null)
                throw new ArgumentNullException("table");

            int counter;
            int num_fields = table.Schema.NumFields;
            IEnumerable<IDBRecord> records = table.Records;
            foreach (IDBRecord record in records)
            {
                counter = 0;
                foreach (IDBData data in record.Contents)
                {
                    writer.Write(data.Data.ToString());
                    if (++counter < num_fields)
                        writer.Write(settings.Delimiter);
                }
                writer.WriteLine();
            }

            writer.WriteLine(settings.SignalEOF);
        }

        private void ExportSchema(TextWriter writer, IDBSchema schema)
        {
            if (writer == null)
                throw new ArgumentNullException("writer");
            else if (schema == null)
                throw new ArgumentNullException("schema");

            IEnumerable<IDBField> fields = schema.Fields;
            foreach (IDBField f in fields)
            {
                writer.Write(f.Name);
                writer.Write(settings.Delimiter);
                writer.Write(f.Type.ToString());
                writer.Write(settings.Delimiter);
                writer.WriteLine(f.IsPrimaryKey.ToString());
            }

            writer.WriteLine(settings.SignalEOF);
        }

        private void ExportTableNames(TextWriter writer, IEnumerable<IDBTable> tables)
        {
            if (writer == null)
                throw new ArgumentNullException("writer");
            else if (tables == null)
                throw new ArgumentNullException("tables");

            foreach (IDBTable table in tables)
                writer.WriteLine(table.Name);

            writer.WriteLine(settings.SignalEOF);
        }
    }
}
